//
//  SquareGenerator.m
//  CocoaSynth
//
//  Created by Pierre DUCHENE on 12/02/10.
//  Copyright 2010 Pierre DUCHENE. All rights reserved.
//

#import "SquareGenerator.h"
#import "SampleProtocol.h"
#import "Sample.h"
#import "System.h"

@implementation SquareGenerator

#pragma mark -
#pragma mark Accessors

@synthesize module;

#pragma mark -
#pragma mark Memory Management

- (id)init
{
	if (self = [super init]) {
		module = nil;
	}
	
	return self;
}

- (void)dealloc
{
	[module release];
	module = nil;
	
	[super dealloc];
}

#pragma mark -
#pragma mark ComputingStrategyProtocol

- (id<SampleProtocol>)execute
{
	id<SampleProtocol> result = [[Sample alloc] init];
	
	// Get system infos
	System* system = [System sharedSystem];
	NSUInteger sampleSize = [system sampleSize];
	double sampleIndex = [system samplePosition];
	double sampleRate = [system sampleRate];
	
	// Get module infos
	float f_0 = [module baseFrequency];
	float k = [module exponentialFrequency];
	NSArray* fm = [[module inputSample] voltages];
	
	
	
	if ((fm == nil) || [[fm objectAtIndex:1] floatValue] != 0) {
		
		NSMutableArray* tempResult = [[NSMutableArray alloc] init];
		float Vfm;
		float f;
		float two_pi = 2 * M_PI;
		float cycleLength;
		for (int i = 0; i < sampleSize; i++) {
			// Compute outputfrequency
			Vfm = [[fm objectAtIndex:i] floatValue];
			f = f_0 * pow(2, (k + Vfm)); // f = f0 * 2^(k+Vfm)
			// Generate a simple sinusoid
			two_pi = 2 * M_PI;
			cycleLength = sampleRate / f;
			float newValue = sin( sampleIndex / cycleLength * two_pi) * kDefaultAmplitude;
			
			// Render the signal squared
			if (newValue > 0) {
				newValue = 1 * kDefaultAmplitude;
			}
			else if (newValue < 0) {
				newValue = -1 * kDefaultAmplitude;
			}
			
			[tempResult insertObject:[NSNumber numberWithFloat:newValue] atIndex:i];
			
			sampleIndex += 1.0;
			if (sampleIndex > cycleLength)
				sampleIndex -= cycleLength;
		}
		[result setVoltages:[NSArray arrayWithArray:tempResult]];
		[tempResult release];
	}
	else {
		[result setVoltages:fm];
	}
	
	[system setSamplePosition:sampleIndex];
	
	return [result autorelease];
}


@end
